#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <stddef.h>


#include <gdiplus.h>
#include <assert.h>

using namespace Gdiplus;

// Reference to the GDI+ static library).
#pragma comment (lib,"Gdiplus.lib")

// Global variables

// The main window class name.
static TCHAR szWindowClass[] = _T("win32app");


// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Win32 Application Hatch Brush");

HINSTANCE hInst;

#define BTN_MYBUTTON_ID_1    503
#define BTN_MYBUTTON_ID_2    504


// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,
		HINSTANCE hPrevInstance,
		LPSTR lpCmdLine,
		int nCmdShow)
{
	UNREFERENCED_PARAMETER(lpCmdLine);
	UNREFERENCED_PARAMETER(hPrevInstance);

	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style          = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc    = WndProc;
	wcex.cbClsExtra     = 0;
	wcex.cbWndExtra     = 0;
	wcex.hInstance      = hInstance;
	wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName   = NULL;
	wcex.lpszClassName  = szWindowClass;
	wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

	if (!RegisterClassEx(&wcex))
	{
		MessageBox(NULL,
				_T("Call to RegisterClassEx failed!"),
				_T("Win32 Guided Tour"),
				NULL);

		return 1;
	}

	hInst = hInstance; // Store instance handle in our global variable

	// The parameters to CreateWindow:
	// szWindowClass: the name of the application
	// szTitle: the text that appears in the title bar
	// WS_OVERLAPPEDWINDOW: the type of window to create
	// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
	// 500, 100: initial size (width, length)
	// NULL: the parent of this window
	// NULL: this application does not have a menu bar
	// hInstance: the first parameter from WinMain
	// NULL: not used in this application
	HWND hWnd = CreateWindow(
			szWindowClass,
			szTitle,
			WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT, CW_USEDEFAULT,
			1000, 500,
			NULL,
			NULL,
			hInstance,
			NULL
			);

	if (!hWnd)
	{
		MessageBox(NULL,
				_T("Call to CreateWindow failed!"),
				_T("Win32 Guided Tour"),
				NULL);

		return 1;
	}

	// Create button controls.
	CreateWindowEx(NULL, L"BUTTON", L"Transparent", WS_VISIBLE | WS_CHILD,
			35, 35, 120, 20, hWnd, (HMENU)BTN_MYBUTTON_ID_1, NULL, NULL);

	CreateWindowEx(NULL, L"BUTTON", L"Opaque", WS_VISIBLE | WS_CHILD,
			35, 65, 120, 20, hWnd, (HMENU)BTN_MYBUTTON_ID_2, NULL, NULL);

	// The parameters to ShowWindow:
	// hWnd: the value returned from CreateWindow
	// nCmdShow: the fourth parameter from WinMain
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	// Main message loop:
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return (int) msg.wParam;
}

/***
 *    This function creates the following rectangles:
 *        1.    An outer rectangle using a solid brush with blue background.
 *        2.    An inner rectangle using a hatch brush with red horizontal lines and yellow background.
 *    It makes the background of the inner rectangle transparent or opaque in function of the user's input.
 *    Inputs: 
 *        1.    hdc, the display device context.
 *        2.    transparent, the hatch brush background user's value; true if transparent, false if opaque.
 ***/
VOID SetHatchBrushBackground(HDC hdc, bool transparent)
{
	// Define a brush handle.
	HBRUSH hBrush;

	// Create a solid blue brush.
	hBrush = CreateSolidBrush(RGB(0, 0, 255));

	// Associate the brush with the display device context.
	SelectObject (hdc, hBrush);

	// Draw a rectangle with blue background.
	Rectangle (hdc,  400,40,800,400);


	// Create a hatch brush that draws horizontal red lines.
	hBrush = CreateHatchBrush(HatchStyleHorizontal, RGB(255, 0, 0));

	// Set the background color to yellow.
	SetBkColor(hdc, RGB(255, 255, 0));


	// Select the hatch brush background transparency based on user's input.
	if (transparent == true)
		// Make the hatch brush background transparent.
		// This displays the outer rectangle blue background.
		SetBkMode(hdc, TRANSPARENT);
	else
		// Make the hatch brush background opaque.
		// This displays the inner rectangle yellow background.
		SetBkMode(hdc, OPAQUE);

	// Associate the hatch brush with the current device context.
	SelectObject(hdc, hBrush);

	// Draw a rectangle with the specified hatch brush.
	Rectangle(hdc,  500,130,700,300);

}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR greeting[] = _T("Select your brush background.");
	TCHAR wmId;
	TCHAR wmEvent;


	switch (message)
	{
		case WM_PAINT:
			hdc = BeginPaint(hWnd, &ps);

			// Start application-specific layout section.
			// Just print the geeting string in the top left corner.
			TextOut(hdc,
					5, 5,
					greeting, (int)_tcslen(greeting));
			// End application-specific layout section.

			// Draw rectangles using hatch brush.
			SetHatchBrushBackground(hdc, true);


			EndPaint(hWnd, &ps);
			break;

		case WM_COMMAND:
			wmId    = LOWORD(wParam);
			wmEvent = HIWORD(wParam);
			hdc = GetDC(hWnd);

			switch (wmId) {

				case BTN_MYBUTTON_ID_1:
					// Draw the inner rectangle using a hatch brush transparent background.
					SetHatchBrushBackground(hdc, true);
					MessageBox(hWnd, _T("Hatch brush background is TRANSPARENT"), _T("Information"), MB_OK);
					break;

				case BTN_MYBUTTON_ID_2:
					// Draw the inner rectangle using a hatch brush opaque background.
					SetHatchBrushBackground(hdc, false);
					MessageBox(hWnd, _T("Hatch brush background is OPAQUE"), _T("Information"), MB_OK);
					break;
			}
			break;

		case WM_DESTROY:
			PostQuitMessage(0);
			break;


		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
			break;
	}

	return 0;
}
